#include <vcl.h>
#pragma hdrstop

#include "uCopier.h"
#include "FileCtrl.hpp"
#include <stdio.h>
#include <errno.h>
#include <io.h>
#include <fcntl.h>
#include <alloc.h>
#include <lmcons.h>
#include <lmmsg.h>
#include "EIC.h"
#include <sys/stat.h>
#include <Masks.hpp>

#pragma package(smart_init)
#pragma resource "*.dfm"

#define MODULE_TAG 3

bool __fastcall CopierRepertoire(const AnsiString &RepertoireSource,const AnsiString &RepertoireDestination,TStringList *ListeFichiersSauf,TStringList *ListeRepertoiresSauf,bool ForcerAToutCopier)
{
  bool Resultat;
  TForm *Fiche;
  AnsiString RepertoireSource2,RepertoireDestination2;
  TdlgCopierFichiers *dlgCopierFichiers = NULL;
  try
    {
      Resultat = false;
      Fiche = Screen->ActiveForm;
      if (Fiche)
        Fiche->Enabled = false;
      dlgCopierFichiers = new TdlgCopierFichiers(0);
      dlgCopierFichiers->Show();
      Application->ProcessMessages();
      RepertoireSource2 = ExcludeTrailingBackslash(RepertoireSource);
      RepertoireDestination2 = ExcludeTrailingBackslash(RepertoireDestination);
      Resultat = dlgCopierFichiers->CopierFichiers(RepertoireSource2,RepertoireDestination2,ListeFichiersSauf,ListeRepertoiresSauf,true,ForcerAToutCopier);
    }
  catch (Exception &e)
    {
      EICDisplayException(TAGL,e);
    }
  if (Fiche)
    Fiche->Enabled = true;
  delete dlgCopierFichiers;
  dlgCopierFichiers = 0;
  return Resultat;
}



bool __fastcall CopierFichier(const AnsiString &FichierSource,const AnsiString &FichierDestination)
{
  bool Resultat;
  TForm *Fiche;
  TdlgCopierFichiers *dlgCopierFichiers = NULL;
  try
    {
      Resultat = false;
      Fiche = Screen->ActiveForm;
      if (Fiche)
        Fiche->Enabled = false;
      dlgCopierFichiers = new TdlgCopierFichiers(0);
      dlgCopierFichiers->Show();
      Application->ProcessMessages();
      Resultat = dlgCopierFichiers->CopierUnFichier(FichierSource,FichierDestination,true);
    }
  catch (Exception &e)
    {
      EICDisplayException(TAGL,e);
    }
  if (Fiche)
    Fiche->Enabled = true;
  delete dlgCopierFichiers;
  dlgCopierFichiers = 0;
  return Resultat;
}



__fastcall TdlgCopierFichiers::TdlgCopierFichiers(TComponent* Owner) : TForm(Owner)
{
  Top = 20;
  Left = 20;
  aAnimation->Active = true;
}



bool __fastcall TdlgCopierFichiers::CopierFichier(const AnsiString &Source,const AnsiString &Destination,bool ForcerAToutCopier)
{
  bool Resultat = false,DestinationExiste = true;
  int FichierSource,FichierDestination;
  long TailleSource,TailleDestination;
  ftime dhSource,dhDestination;
  char Chaine[8192 + 1];
  try
    {
      labelFichiers->Caption = MinimizeName(Destination,labelFichiers->Canvas,labelFichiers->Width);
      FichierSource = FichierDestination = 0;
      if (access(Source.c_str(),6) != 0)
        chmod(Source.c_str(),S_IREAD | S_IWRITE);
      if (access(Destination.c_str(),6) != 0)
        {
          if (errno == EACCES)
            chmod(Destination.c_str(),S_IREAD | S_IWRITE);
          else
            DestinationExiste = false;
        }
      FichierSource = open(Source.c_str(),O_RDONLY | O_BINARY);
      if (getftime(FichierSource,&dhSource))
        Abort();
      if (DestinationExiste && !ForcerAToutCopier)
        {
          TailleSource = filelength(FichierSource);
          FichierDestination = open(Destination.c_str(),O_RDONLY | O_BINARY);
          TailleDestination = filelength(FichierDestination);
          getftime(FichierDestination,&dhDestination);
          close(FichierDestination);
        }
      else
        ForcerAToutCopier = true;
      if (!ForcerAToutCopier && (TailleSource == TailleDestination) && !memcmp(&dhSource,&dhDestination,sizeof(ftime)))
        {//Les fichiers sont identiques
          close(FichierSource);
          m_TailleFichiersCopies += TailleSource;
          pbFichiers->Position = (int)((double)((double)m_TailleFichiersCopies / (double)m_TailleFichiersACopier) * 100.0);
          return true;
        }
      FichierDestination = open(Destination.c_str(),O_RDWR | O_CREAT | O_TRUNC | O_BINARY,S_IREAD | S_IWRITE);
      if ((FichierSource <= 0) || (FichierDestination <= 0))
        Abort();
      do
        {
          TailleSource = read(FichierSource,Chaine,8192);
          TailleDestination = write(FichierDestination,Chaine,TailleSource);
          if (TailleDestination > 0)
            m_TailleFichiersCopies += TailleDestination;
          pbFichiers->Position = (int)((double)((double)m_TailleFichiersCopies / (double)m_TailleFichiersACopier) * 100.0);
          if (pbFichiers->Position != 0)
            pbFichiers->Position = pbFichiers->Position;
          if (TailleDestination != TailleSource)
            Abort();
          Application->ProcessMessages();
          if (ModalResult != mrNone)
            Abort();
        }
      while (TailleSource == 8192);
      Resultat = true;
      setftime(FichierDestination,&dhSource);    //On force la date et l'heure du fichier copié pour qu'il soit identique à la source
    }
  catch (Exception &e)
    {
      labelFichiers->Font->Color = clRed;
      switch (errno)
        {
          case EACCES:
            labelErreur->Caption = "Permission refusée";
            break;
          case EMFILE:
            labelErreur->Caption = "Trop de fichiers ouverts";
            break;
          case ENOENT:
            labelErreur->Caption = "Fichier introuvable";
            break;
          default:
            labelErreur->Caption = "Erreur de copie ou permission refusée";
            break;
        }
    }
  if (FichierSource)
    close(FichierSource);
  if (FichierDestination)
    close(FichierDestination);
  return Resultat;
}



bool __fastcall TdlgCopierFichiers::CopierFichiers(const AnsiString &Source,const AnsiString &Destination,TStringList *ListeFichiersSauf,TStringList *ListeRepertoiresSauf,bool CalculerTaille,bool ForcerAToutCopier)
{
  bool FichierCopie,Sauf;
  TSearchRec SearchRec;
  try
    {
      FichierCopie = false;
      if (CalculerTaille)
        m_TailleFichiersACopier = TailleFichiers(Source,ListeFichiersSauf,ListeRepertoiresSauf);
      if (FindFirst(Source + "\\*.*",faAnyFile,SearchRec) == 0)
        {
          labelFichiers->Caption = MinimizeName(AnsiString("Création du répertoire : ") + Destination,labelFichiers->Canvas,labelFichiers->Width);
          Application->ProcessMessages();
          if (!DirectoryExists(Destination) && !CreateDir(Destination))
            throw Exception(AnsiString("Impossible de créer le répertoire\n'") + Destination + "'.");
          do
            {
              if (ModalResult != mrNone)
                break;
              if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
                {
                  if (SearchRec.Attr & faDirectory)
                    {
                      if (ListeRepertoiresSauf)
                        {
                          Sauf = true;
                          for (int i = 0;i < ListeRepertoiresSauf->Count;i++)
                            if (MatchesMask(SearchRec.Name,ListeRepertoiresSauf->Strings[i]))
                              {//Ce répertoire est dans la liste des répertoires à ne pas copier...
                                Sauf = false;
                                break;
                              }
                          if (!Sauf)
                            continue;   //...on ne le copie pas
                        }
                      FichierCopie = CopierFichiers(Source + "\\" + SearchRec.Name,Destination + "\\" + SearchRec.Name,ListeFichiersSauf,ListeRepertoiresSauf,false,ForcerAToutCopier);
                    }
                  else
                    {
                      if (ListeFichiersSauf)
                        {
                          Sauf = true;
                          for (int i = 0;i < ListeFichiersSauf->Count;i++)
                            if (MatchesMask(SearchRec.Name,ListeFichiersSauf->Strings[i]))
                              {//Ce fichier est dans la liste des fichiers à ne pas copier...
                                Sauf = false;
                                break;
                              }
                          if (!Sauf)
                            continue;   //...on ne le copie pas
                        }
                      labelFichiers->Font->Color = clWindowText;
                      labelErreur->Caption = EmptyStr;
                      while (!(FichierCopie = CopierFichier(Source + "\\" + SearchRec.Name,Destination + "\\" + SearchRec.Name,ForcerAToutCopier)))
                        {
                          Application->ProcessMessages();
                          if (ModalResult != mrNone)
                            break;
                        }
                    }
                }
            }
          while (FindNext(SearchRec) == 0);
        }
      FindClose(SearchRec);
    }
  catch (Exception &e)
    {
      EICDisplayException(TAGL,e);
    }
  return FichierCopie;
}



bool __fastcall TdlgCopierFichiers::CopierUnFichier(const AnsiString &Source,const AnsiString &Destination,bool CalculerTaille)
{
  bool FichierCopie;
  try
    {
      FichierCopie = false;
      if (CalculerTaille)
        m_TailleFichiersACopier = TailleUnFichier(Source);
      labelFichiers->Font->Color = clWindowText;
      labelErreur->Caption = EmptyStr;
      while (!(FichierCopie = CopierFichier(Source,Destination,true)))
        {
          Application->ProcessMessages();
          if (ModalResult != mrNone)
            break;
        }
    }
  catch (Exception &e)
    {
      EICDisplayException(TAGL,e);
    }
  return FichierCopie;
}



unsigned __int64 __fastcall TdlgCopierFichiers::TailleFichiers(const AnsiString &Source,TStringList *ListeFichiersSauf,TStringList *ListeRepertoiresSauf)
{
  unsigned __int64 Taille;
  int Fichier;
  bool Sauf;
  TSearchRec SearchRec;
  Taille = 0ui64;
  labelFichiers->Caption = "Initialisations";
  Application->ProcessMessages();
  if (FindFirst(Source + "\\*.*",faAnyFile,SearchRec) == 0)
    {
      do
        {
          if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
            {
              if (SearchRec.Attr & faDirectory)
                {
                  if (ListeRepertoiresSauf)
                    {
                      Sauf = true;
                      for (int i = 0;i < ListeRepertoiresSauf->Count;i++)
                        if (MatchesMask(SearchRec.Name,ListeRepertoiresSauf->Strings[i]))
                          {//Ce répertoire est dans la liste des répertoires à ne pas copier...
                            Sauf = false;
                            break;
                          }
                      if (!Sauf)
                        continue;   //...on ne le copie pas
                    }
                  Taille += TailleFichiers(Source + "\\" + SearchRec.Name,ListeFichiersSauf,ListeRepertoiresSauf);
                }
              else
                {
                  if (ListeFichiersSauf)
                    {
                      Sauf = true;
                      for (int i = 0;i < ListeFichiersSauf->Count;i++)
                        if (MatchesMask(SearchRec.Name,ListeFichiersSauf->Strings[i]))
                          {//Ce fichier est dans la liste des fichiers à ne pas copier...
                            Sauf = false;
                            break;
                          }
                      if (!Sauf)
                        continue;   //...on ne le copie pas
                    }
                  Fichier = open((Source + "\\" + SearchRec.Name).c_str(),O_RDONLY | O_BINARY);
                  Taille += filelength(Fichier);
                  close(Fichier);
                }
            }
        }
      while (FindNext(SearchRec) == 0);
    }
  FindClose(SearchRec);
  return Taille;
}



unsigned __int64 __fastcall TdlgCopierFichiers::TailleUnFichier(const AnsiString &Source)
{
  unsigned __int64 Taille;
  int Fichier;
  Taille = 0ui64;
  labelFichiers->Caption = "Initialisations";
  Application->ProcessMessages();
  Fichier = open(Source.c_str(),O_RDONLY | O_BINARY);
  Taille = filelength(Fichier);
  close(Fichier);
  return Taille;
}



void __fastcall TdlgCopierFichiers::BitBtn1Click(TObject *Sender)
{
  if (::MessageBox(Handle,"Voulez-vous abandonner la copie des fichiers ?","Annulation de la mise à jour du communlocal",MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
    ModalResult = mrCancel;
}



